package pl.edu.agh.jemo.evolution.metrics.impl;

import java.math.BigDecimal;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import org.apache.log4j.Logger;

import pl.edu.agh.jemo.evolution.metrics.Metric;
import pl.edu.agh.jemo.evolution.population.Population;
import pl.edu.agh.jemo.evolution.specimen.Specimen;

/**
 * 
 * 2D metric
 * 
 */
public class HypervolumeMetric implements Metric {

	private Logger logger = Logger.getLogger(HypervolumeMetric.class);

	private static final String NAME = "Hypervolume";

	private final BigDecimal referencePointX;
	private final BigDecimal referencePointY;

	@Override
	public String getName() {
		return NAME;
	}
	

	
	@Override
	public BigDecimal getValue(Population population) {
		SortedMap<BigDecimal, BigDecimal> sortedSpecimen = new TreeMap<BigDecimal, BigDecimal>();
		for (final Specimen specimen : population) {
			// Y value goes first
			sortedSpecimen.put(new BigDecimal(specimen.getPhenotype()[1]),
					new BigDecimal(specimen.getPhenotype()[0]));
		}
		BigDecimal result = BigDecimal.ZERO;
		BigDecimal lastPoint = referencePointY;
		for (final Map.Entry<BigDecimal, BigDecimal> entry : sortedSpecimen
				.entrySet()) {
			final BigDecimal area = (lastPoint.subtract(entry.getKey()).abs())
					.multiply(referencePointX.subtract(entry.getValue()).abs());
			logger.debug("area " + area + " for point [" + entry.getValue()
					+ ", " + entry.getKey() + "]");
			result = result.add(area);
			lastPoint = entry.getKey();
		}
		return result;
	}

	/**
	 * (x, y) is the metrics reference point
	 * 
	 * @param x
	 * @param y
	 */
	public HypervolumeMetric(BigDecimal x, BigDecimal y) {
		this.referencePointX = x;
		this.referencePointY = y;
	}
}
